#include "bookunrar.h"
#include "bookitemlist.h"
#include <QByteArray>
#include <QImageReader>
#include "book.h"

const QString UnrarExe("/opt/meecomicui/bin/unrar");

BookUnrar::BookUnrar(QObject *parent):
    QObject(parent),
    m_state(Nothing),
    m_pageCount(0),
    m_files(0)
{
    m_process = new QProcess(this);
    connect(m_process,SIGNAL(error(QProcess::ProcessError)),this,SLOT(onError(QProcess::ProcessError)));
    connect(m_process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(onFinished(int,QProcess::ExitStatus)));
    connect(m_process,SIGNAL(readyReadStandardError()),this,SLOT(onReadyReadStandardError()));
    connect(m_process,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadyReadStandardOutput()));

    m_process->setWorkingDirectory("/opt/meecomicui/bin");

    m_queueExtractFile = new BookUnrarQueueThread(BookUnrarQueueThread::PageImage);
    m_queueFirstPage = new BookUnrarQueueThread(BookUnrarQueueThread::PageName);
    connect(m_queueExtractFile,SIGNAL(queueNext(Book*)),this,SLOT(startExtractFile(Book*)));
    connect(m_queueFirstPage,SIGNAL(queueNext(Book*)),this,SLOT(startFirstImage(Book*)));
}

void BookUnrar::setArchiveName(QString text)
{
    m_archiveName = text;
}

void BookUnrar::extractAll()
{
    if(!m_archiveName.isEmpty()){
        m_state = Extract;
        m_files = 0;
        m_params = QStringList() << "e" << "-o+" << "-p-" << m_archiveName << PRIVATE_BOOKDIR_EXTRACTED+"/";
        m_process->start(UnrarExe,m_params);
    }
}

void BookUnrar::extractFile(Book* book)
{
    if(book != NULL){
        m_queueExtractFile->append(book);
        if(!m_queueFirstPage->isRunning() && m_process->state() == QProcess::NotRunning)
            m_queueExtractFile->next();
    }
}

void BookUnrar::startExtractFile(Book* book)
{
    if(book != NULL){
        m_state = ExtractFile;
        m_params = QStringList() << "x" << "-o+" << "-p-" << book->getBookArchiveName() << book->getFirstPageFilename() << PRIVATE_BOOKDIR_EXTRACTED+"/";
        m_currentBook = book;
        m_process->start(UnrarExe,m_params);
    }
}

void BookUnrar::startFirstImage(Book* book)
{
    if(!book->getBookArchiveName().isEmpty()){
        m_state = FirstPage;
        m_params = QStringList() << "vb" << book->getBookArchiveName();
        m_currentBook = book;
        m_process->start(UnrarExe,m_params);
    }
}

void BookUnrar::getFirstImage(Book* book)
{
    if(!book->getBookArchiveName().isEmpty()){
        m_queueFirstPage->append(book);
        if(!m_queueExtractFile->isRunning() && m_process->state() == QProcess::NotRunning)
            m_queueFirstPage->next();
    }
}

void BookUnrar::getPageCount()
{
    if(!m_archiveName.isEmpty()){
        m_state = PageCount;
        m_pageCount = 0;
        m_params = QStringList() << "l" << m_archiveName;
        m_process->start(UnrarExe,m_params);
    }
}

void BookUnrar::onError(QProcess::ProcessError error )
{
    Q_UNUSED(error);
    m_process->terminate();
}

void BookUnrar::onFinished( int exitCode, QProcess::ExitStatus exitStatus )
{
    qDebug() << "exitCode: " << exitCode << " exitStatus: " << exitStatus;
    BookItemList::ErrorCodes code(BookItemList::NoError);

    if(exitStatus == QProcess::CrashExit)
        code = BookItemList::ZipBroken;
    if(exitCode)
        code = BookItemList::ZipBroken;

    Book* sendBack = NULL;
    if(m_currentBook!=NULL)
        sendBack = m_currentBook;
    m_currentBook = NULL;

    QString pageName;
    pageName = m_firstPage;
    m_firstPage.clear();

    switch(m_state){
    case PageCount:{
        emit this->pageCount(m_pageCount);
    }break;
    case FirstPage:{
        extractFile(sendBack);
        if(m_queueFirstPage->haveItems())
            m_queueFirstPage->next();
        else if(m_queueExtractFile->haveItems())
            m_queueExtractFile->next();
    }break;
    case Extract:{
        emit this->extractFinished(code);
    }break;
    case ExtractFile:{
        if(m_queueExtractFile->haveItems())
            m_queueExtractFile->next();
        emit this->firstImageExtracted(code,sendBack);
    }break;

    default:break;
    }
}

void BookUnrar::onReadyReadStandardError()
{
    if(m_process->state() == QProcess::Running)
        m_process->terminate();
}

void BookUnrar::onReadyReadStandardOutput()
{
    while(m_process->canReadLine()){
        QString stdLine;
        QByteArray tmpline = m_process->readLine();
        stdLine = QString::fromUtf8(tmpline);
        stdLine = stdLine.trimmed();

        switch(m_state){
        case Extract:{
            if(stdLine.startsWith("Extracting") && stdLine.endsWith("OK")){
                m_files++;
                emit this->openedZipPage(m_files,m_pageCount,QString());
            }
        }break;
        case FirstPage:{
            if(m_firstPage.isEmpty()){
                QList<QByteArray> sported = QImageReader::supportedImageFormats();
                foreach(QByteArray e,sported){
                    QString ext("."+e);
                    QString fname;
                    int ind = stdLine.indexOf(ext,0,Qt::CaseInsensitive);
                    if(ind>-1){
                        fname = stdLine.mid(0,ind);
                        fname.append(stdLine.mid(ind,ext.length()));
                        m_firstPage = fname;
                        m_currentBook->setFirstPageFilename(m_firstPage);
                    }
                }
            }
        }break;

        case ExtractFile:{
            if(stdLine.startsWith("Extracting") && stdLine.endsWith("OK")){
                m_firstPage = PRIVATE_BOOKDIR_EXTRACTED+"/"+m_currentBook->getFirstPageFilename();

                QFile file(m_firstPage);
                if(file.open(QIODevice::ReadOnly) && m_currentBook != NULL){
                    QImage img;
                    QString imgname = m_firstPage;
                    imgname = imgname.replace(QRegExp("\\s"),QString("_"));
                    imgname = imgname.replace(QRegExp("\\W"),QString("_"));
                    imgname = PRIVATE_BOOKDIR_THUMBS+"/"+imgname+".png";
                    img.loadFromData(file.readAll());
                    img = img.scaled(SCALED_ICON_SIZE);
                    img.save(imgname);

                    m_currentBook->setListImage(QUrl(imgname));
                    file.close();
                }
            }
        }break;

        default:break;
        }
    }
}
